/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.web.gwt.form.client.widget.item.impl;

import java.util.ArrayList;
import java.util.List;

import com.genia.toolbox.web.gwt.basics.client.GwtHelper;
import com.genia.toolbox.web.gwt.basics.client.i18n.GwtI18nMessage;
import com.genia.toolbox.web.gwt.form.client.CssNames;
import com.genia.toolbox.web.gwt.form.client.form.ListBoxInterface;
import com.genia.toolbox.web.gwt.form.client.form.ValuedItemEntry;
import com.genia.toolbox.web.gwt.form.client.widget.item.ItemWidgetModifyListener;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Widget;

/**
 * the implementation of <code>SimpleItemWidget</code> for a
 * <code>ListBoxItem</code>.
 * 
 * @param <ITEM>
 *          the type of item handled by this widget.
 */
public abstract class AbstractListBoxItemWidget<ITEM extends ListBoxInterface>
    extends AbstractSimpleItemWidget<ITEM>
{

  /**
   * the <code>ListBox</code> being displayed.
   */
  private transient ListBox listBox = null;

  /**
   * the main panel of the <code>Composite</code>.
   */
  private final transient HorizontalPanel hPanel = new HorizontalPanel();

  /**
   * the list of all the <code>Widget</code> that must be modify to update the
   * error message.
   */
  private final transient Widget[] widgetsToToggle = new Widget[] { listBox, hPanel };

  /**
   * the values to set once the initialization is done.
   */
  private transient List<String> currentValues = null;

  /**
   * the registered listeners.
   */
  private ItemWidgetModifyListenerCollection itemWidgetModifyListenerCollection = new ItemWidgetModifyListenerCollection();



  /**
   * setting the different values of this item.
   * 
   * @param item
   *          the {@link ListBoxInterface} representing this object
   * @param valuedItemEntrys
   *          the entries of this item
   */
  protected void setValuedItemEntrys(final ITEM item, final List<ValuedItemEntry> valuedItemEntrys)
  {
    listBox = new ListBox();
    // set the subValues and the subLabels.
    for (final ValuedItemEntry entry : valuedItemEntrys) {
      GwtHelper.addToListBox(listBox, entry.getLabel(), entry.getValue());
    }

    listBox.setMultipleSelect(item.isMultipleSelect());
    listBox.setName(item.getName());
    listBox.setVisibleItemCount(item.getVisibleItemCount());
    listBox.setEnabled(item.isEnabled());
    hPanel.add(listBox);
    listBox.addChangeListener(new ChangeListener()
    {
      public void onChange(final Widget widget)
      {
        itemWidgetModifyListenerCollection.onModify(AbstractListBoxItemWidget.this);
      }
    });
    setValues(currentValues);
    currentValues = null;
  }



  /**
   * constructor.
   * 
   * @param item
   *          the item this object represents.
   */
  public AbstractListBoxItemWidget(final ITEM item)
  {
    super(item);

    // get properties from a ListBoxItem.
    final GwtI18nMessage labelListBox = item.getLabelKey();

    // get widgets.
    final Label label = new Label();

    // set the i18nMessage to the label.
    GwtHelper.fillText(label, labelListBox);

    hPanel.addStyleName(CssNames.LISTBOX_PANEL_CSS_STYLE);
    hPanel.addStyleName(item.getName());

    // add widgets to the panel.
    hPanel.add(label);
    initWidget(hPanel);
  }



  /**
   * returns the current value of the <code>ListBox</code>.
   * 
   * @return the current value of the <code>ListBox</code>
   */
  public List<String> getValues()
  {
    if (listBox == null) {
      return currentValues;
    }
    if (listBox.getSelectedIndex() == -1) {
      return null;
    }
    List<String> res = new ArrayList<String>();
    for (int i = 0; i < listBox.getItemCount(); i++) {
      if (listBox.isItemSelected(i)) {
        res.add(listBox.getValue(i));
      }
    }
    if (res.isEmpty()) {
      return null;
    }
    return res;
  }



  /**
   * add a listener that is called each time the value of this object change.
   * 
   * @param modifyListener
   *          the callback
   */
  public void addModifyListener(final ItemWidgetModifyListener modifyListener)
  {
    itemWidgetModifyListenerCollection.add(modifyListener);
  }



  /**
   * set the current values of the <code>ListBox</code>.
   * 
   * @param values
   *          the current values of the <code>ListBox</code>
   */
  public void setValues(final List<String> values)
  {
    if (listBox == null) {
      currentValues = values;
    }
    else {
      for (int i = 0; i < listBox.getItemCount(); i++) {
        listBox.setItemSelected(i, values != null && values.contains(listBox.getValue(i)));
      }
    }
  }



  /**
   * getter for the widgetsToToggle property.
   * 
   * @return the widgetsToToggle
   */
  @Override
  protected Widget[] getWidgetsToToggle()
  {
    return widgetsToToggle;
  }

}
